package com.yami.shop.webservice.api.controller;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.MailException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.model.*;
import com.yami.shop.common.bean.HSExchange;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.DataWebService;
import com.yami.shop.common.util.Json;
import com.yami.shop.config.ShopConfig;
import com.yami.shop.personnft.common.model.PersonNft;
import com.yami.shop.personnft.common.model.TransferApplyRecord;
import com.yami.shop.personnft.common.model.TransferBatchApply;
import com.yami.shop.personnft.common.service.*;
import com.yami.shop.service.ChannelUserRelationRecordService;
import com.yami.shop.service.ProdNftService;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.UserService;
import com.yami.shop.webservice.common.model.DawFromVo;
import com.yami.shop.webservice.common.service.TransferTokenRecordService;
import lombok.Synchronized;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 *
 * @ClassName:
 * @Description: 业务接口
 * @Author:
 * @Date: 2
 * @History 修改描述
 */
@RestController
@RequestMapping( "/nftVerifyApply")
public class CardWSController {
	private final Logger log = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private PersonNftApplyService personNftApplyService;
	@Autowired
	private PersonNftService personNftService;
	@Autowired
	private UserService userService;
	@Autowired
	private TransferTokenRecordService transferTokenRecordService;
	@Autowired
	private NftTansferEnpandService nftTansferEnpandService;
	@Autowired
	private TransferApplyService transferApplyService;
	@Autowired
	private DataWebService dataWebService;
	@Autowired
	private ProductService productService;
	@Autowired
	private ChannelUserRelationRecordService channelUserRelationRecordService;
	@Autowired
	private ShopConfig shopConfig;
	@Autowired
	private ProdNftService prodNftService;
	@Autowired
	private TransferBatchApplyService transferBatchApplyService;
	/**
	 * 申请提现  一个申请提现中必须一人人，一个商品 这样保证 该申请能同时成功或失败
	 *
	 * @param
	 * @return
	 * @description: 卡提现审核
	 */
	@RequestMapping( "/verifyApply")
	@ResponseBody
	public ServerResponseEntity verifyApply(@Valid @RequestBody Map<String,Object> jSONObject) {
		Map<String,Object> hashMap = new HashMap<>();
		try {
			log.info("申请提现参数：" + Json.toJsonString(jSONObject));
			dataWebService.checkSign(jSONObject,hashMap,null);
			verifyApplyDeatil(jSONObject);
			return ServerResponseEntity.success();
		} catch (MailException e) {
			e.printStackTrace();
			log.error("申请业务异常: " + e.getMessage() + "\r\n" + Arrays.toString(e.getStackTrace()));
			return ServerResponseEntity.showFailMsg("申请异常");
		}catch (Exception e){
			log.error("申请异常: " + e.getMessage() + "\r\n" + Arrays.toString(e.getStackTrace()));
			return ServerResponseEntity.showFailMsg(e.getMessage());
		}
	}

	public void verifyApplyDeatil(Map<String,Object> jSONObject) throws MailException, YamiShopBindException {
		if (null != jSONObject) {
			JSONArray dataList = JSON.parseArray(JSON.toJSONString(jSONObject.get("dataList")));
			String applyId = jSONObject.get("applyId").toString();
			List<DawFromVo> list = new ArrayList<>();
			if(dataList.size()==0){
				throw new YamiShopBindException("交收数据为空");
			}
			List<String> varietyCodes = dataList.stream().map(s -> ((JSONObject) s).getString("varietyCode")).distinct().collect(Collectors.toList());
			if(varietyCodes.size()!=1){
				throw new YamiShopBindException("单次申请提现请提交单一商品");
			}
			//多商品校验备用
//			List<PersonnftTansferEnpand> byVarietyCodes = nftTansferEnpandService.getByVarietyCodes(varietyCodes);
//			Map<Long, PersonnftTansferEnpand> enpandMap = byVarietyCodes.stream().collect(Collectors.toMap(PersonnftTansferEnpand::getProdId, Function.identity()));
//			List<Long> collect = byVarietyCodes.stream().map(s -> s.getProdId()).distinct().collect(Collectors.toList());
//			Map<Long, Product> mapByProdIds = productService.getMapByProdIds(collect);
//			Collection<Product> values = mapByProdIds.values();
//			ArrayList<Product> products = new ArrayList<>(values);
//			for (Product product:products) {
//				//校验钱包
//				ChannelUserRelationRecord record = channelUserRelationRecordService.getinfoByUserIdChainCodeChannelCode(userApiVO.getUserId(), product.getChain(), product.getChannelCode(), String.valueOf(product.getSource() + 1));
//				if(ObjectUtil.isNull(record)){
//					throw  new YamiShopBindException("提示:请您先在dtc++创建对应链钱包");
//				}
//			}
			String idType = jSONObject.get("idType").toString();
			String idNumber = jSONObject.get("idNumber").toString();
			//dtc提现证件号校验
			List<User> lsit = userService.list(new LambdaQueryWrapper<User>().eq(User::getIdNumber, idNumber).eq(User::getStatus,1));
			if(lsit==null || lsit.size()==0){
				throw  new YamiShopBindException("提示:请您先在dtc++注册并用交易系统证件号码实名后在试");
			}else if( lsit.size()>1){
				throw  new YamiShopBindException("提示:dtc该实名数据过多");
			}
			//如果是下游资产提现 需要判断用户是否导入过下游资产，过没有需先添加下游钱包
			String varietyCode = varietyCodes.get(0);
			//验证编码
			PersonnftTansferEnpand byVarietyCode = nftTansferEnpandService.getByVarietyCode(varietyCode);
			if(byVarietyCode==null){
				throw  new YamiShopBindException("没有该品类");
			}
			Product productByProdId = productService.getProductByProdId(byVarietyCode.getProdId());
			User  userApiVO  = lsit.get(0);
			log.info("提现证件号"+idNumber+"varietyCode"+varietyCode);
			if(StrUtil.isEmpty(userApiVO.getSettleAccount())){
				throw  new YamiShopBindException("提示:请您先在dtc++绑定交易系统的账户后再次尝试");
			}
			ProdNft dataByProdId = prodNftService.getDataByProdId(byVarietyCode.getProdId());
			//校验钱包
			ChannelUserRelationRecord record = channelUserRelationRecordService.getinfoByUserIdChainCodeChannelCode(userApiVO.getUserId(), productByProdId.getChain(), productByProdId.getChannelCode(), String.valueOf(productByProdId.getSource() + 1));
			if(ObjectUtil.isNull(record)){
				throw  new YamiShopBindException("提示:请您先在dtc++创建对应链钱包");
			}
			for (Object object:dataList) {
				JSONObject obj  = (JSONObject)object;
				JSONObject objEnp = obj.getJSONObject("dataMap");
				if(ObjectUtil.isNull(objEnp)||StrUtil.isEmpty(objEnp.getString("tokenId"))){
					throw new YamiShopBindException("tokenId不能为空");
				}
				DawFromVo dawPerFromVo = new DawFromVo();
				dawPerFromVo.setTokenId(objEnp.getString("tokenId"));
				dawPerFromVo.setIdType(idType);
				dawPerFromVo.setIdNumber(idNumber);
				dawPerFromVo.setProdName(productByProdId.getProdName());
				dawPerFromVo.setProdId(byVarietyCode.getProdId());
				dawPerFromVo.setDenomId(dataByProdId.getDenomId());
				list.add(dawPerFromVo);
			}

			TransferApplyRecord transferApplyRecord = new TransferApplyRecord();
			transferApplyRecord.setId(applyId);
			transferApplyRecord.setCreateTime(DateUtil.date());
			transferApplyRecord.setType(1);//转入
			transferApplyRecord.setTimes(0);
			transferApplyRecord.setContent(Json.toJsonString(jSONObject));
			try {
				String appId = insertVerifyNftApply(list,applyId,userApiVO.getUserId());
				transferApplyRecord.setStatus(1);//待处理
				transferApplyRecord.setAppId(appId);
			}catch (Exception e){
				transferApplyRecord.setStatus(2);//待查询
				transferApplyRecord.setAppId("00000000");
				String msg = getString(e);
				transferApplyRecord.setMsg(msg);
				log.info(e.getMessage());
				throw new MailException(e.getMessage());
			}finally {
				transferApplyService.save(transferApplyRecord);
			}
		}else{
			throw  new MailException("biz_content为空");
		}
	}
	private String getString(Exception e) {
		String msg = "";
		if(StrUtil.isEmpty(e.getMessage())&& Arrays.toString(e.getStackTrace()).length()<=490){
			msg = "null--"+ Arrays.toString(e.getStackTrace()).substring(0);
		}else if(StrUtil.isEmpty(e.getMessage())&&Arrays.toString(e.getStackTrace()).length()>490){
			msg = "null--"+ Arrays.toString(e.getStackTrace()).substring(0,490);
		}else if(e.getMessage().length()>500){
			msg = e.getMessage().substring(0,500);
		}else{
			msg = e.getMessage().substring(0);
		}
		return msg;
	}
	/**
	 * 提现更新提现规则商城提现 提现校验并插入申请表
	 */
	@Synchronized
	private String  insertVerifyNftApply(List<DawFromVo> dawPerFromVoList,String applyId,String userId){
		List<PersonNft> reslist = new ArrayList<>();
		String isListClick = "";//这里用做提现区分
		String channelType = "1";
		String appId= IdUtil.getSnowflake().nextIdStr();
		Product productByProdId = productService.getProductByProdId(dawPerFromVoList.get(0).getProdId());//暂时支持单次单人同一种商品
		String content = "";
		for (DawFromVo dawPerFromVo  : dawPerFromVoList) {
			List<String> prodIds = Arrays.asList(shopConfig.getVerifyProdid().split(","));
			//正在申请的只能有一条
			PersonNftApply param = PersonNftApply.builder().status(0).sceneType("2").content(dawPerFromVo.getTokenId()).build();
			List<PersonNftApply>  list = personNftApplyService.listByParam(param);
			if(list.size()>0){
				throw new MailException("重复提交交收数据");
			}
			PersonNft personNft = PersonNft.builder().tokenId(dawPerFromVo.getTokenId()).status(4).build();
			List<PersonNft> personNfts = personNftService.listByParam(personNft);
			if(1 == productByProdId.getSource()){//下游提现
				TransferTokenRecord record= transferTokenRecordService.selectByTokenId(dawPerFromVo.getTokenId(),0);
				if(ObjectUtil.isNull(record)){
					throw new MailException("商城无划转记录");
				}else if(record.getStatus()==1){
					throw new MailException("提示:划转未结束，稍后在试");
				}
				dawPerFromVo.setDenomId(record.getDenomeId());//二级id 替换一级
				//下游提现
				PersonNft person = new PersonNft();
				person.setTokenId(dawPerFromVo.getTokenId());
				person.setChannelCode(productByProdId.getChannelCode());
				person.setChainCode(productByProdId.getChain());
				person.setDenomId(dawPerFromVo.getDenomId());
				person.setProductId(dawPerFromVo.getProdId());
				reslist.add(person);
				channelType = "2";
				isListClick = "N";
				content = String.join(",", reslist.stream().map(s -> s.getTokenId()).collect(Collectors.toList()));
				//保存批次表，下游提现需要转移资产
				TransferBatchApply transferBatchApply = TransferBatchApply.builder()
						.applyId(appId)
						.content(content)
						.status(4)  //托管账户转出
						.times(0)
						.createTime(new Date())
						.chainCode(productByProdId.getChain())
						.channelCode(productByProdId.getChannelCode())
						.channelType(channelType)
						.surplusContent(content)
						.build();
				transferBatchApplyService.save(transferBatchApply);
			}else if(prodIds.size()== 0 || !prodIds.contains(dawPerFromVo.getProdId().toString()) || (prodIds.contains(dawPerFromVo.getProdId().toString()) && personNfts.size()>0)) {
				//正常划转的提现逻辑
				//校验
				TransferTokenRecord record= transferTokenRecordService.selectByTokenId(dawPerFromVo.getTokenId(),0);
				if(ObjectUtil.isNull(record)){
					throw new MailException("商城无划转记录");
				}else if(record.getStatus()==1){
					throw new MailException("提示:划转未结束，稍后在试");
				}
				PersonNft person = personNfts.get(0);
				reslist.add(person);
				List<PersonNft> collect = personNfts.stream().filter(PersonNft -> PersonNft.getStatus() != 2).collect(Collectors.toList());
				if(collect!=null && collect.size()>0){
					throw new MailException("唯一值重复，{}",dawPerFromVo.getTokenId());
				}
				isListClick = "N";
			}else{
				// 海文交当方提现数据 要提现空投的数据
				PersonNft person = new PersonNft();
				person.setTokenId(dawPerFromVo.getTokenId());
				person.setChannelCode(productByProdId.getChannelCode());
				person.setChainCode(productByProdId.getChain());
				person.setDenomId(dawPerFromVo.getDenomId());
				person.setProductId(dawPerFromVo.getProdId());
				reslist.add(person);
				isListClick = "Y";
			}
		}
		if(StrUtil.isEmpty(content)){
			content = String.join(",", reslist.stream().map(s -> s.getTokenId()).collect(Collectors.toList()));
		}
		String productCode = String.join(",", reslist.stream().filter(s->!ObjectUtil.isNull(s.getDawProductCode())).map(s -> s.getDawProductCode()).collect(Collectors.toList()));
		//保存提现记录
		PersonNftApply personNftApply = PersonNftApply.builder()
				.createTime(DateUtil.date())
				.id(appId)
				.content(content)
				.sceneType("2")
				.status(0)
				.channelType(channelType)
				.chainCode(reslist.get(0).getChainCode())
				.channelCode(reslist.get(0).getChannelCode())
				.denomId(reslist.get(0).getDenomId())
				.userId(userId)
				.count(dawPerFromVoList.size())
				.productId(reslist.get(0).getProductId())
				.dawProductCode(productCode)
				.isListClick(isListClick)
				.build();
		if("2".equals(personNftApply.getChannelType())){//创建下游申请表id 保障上下游有唯一id记录
			personNftApply.setDownApplyId(IdUtil.getSnowflake().nextIdStr());
		}
		personNftApplyService.save(personNftApply);
		return appId;
	}

	/**
	 * 申请提现
	 *
	 * @param
	 * @return
	 * @description: 卡提现审核
	 */
	@RequestMapping( "/verifyNftApplyCheck")
	@ResponseBody
	public 	ServerResponseEntity verifyNftApplyCheck(@Valid @RequestBody Map<String,Object> jSONObject) {
		Map<String,Object> hashMap = new HashMap<>();
		try {
			log.info("申请提现参数：" + Json.toJsonString(jSONObject));
			dataWebService.checkSign(jSONObject,hashMap,null);
			return ServerResponseEntity.success(verifyNftApplyCheckDetail(hashMap));
		} catch (Exception e) {
			e.printStackTrace();
			log.error("申请异常: " + e.getMessage() + "\r\n" + Arrays.toString(e.getStackTrace()));
			return ServerResponseEntity.success(e.getMessage());
		}
	}

	public JSONArray verifyNftApplyCheckDetail(	Map<String,Object> hashMap) throws YamiShopBindException {
		log.info("入参biz_content，{}",hashMap);
		JSONArray jSONArray = JSONArray.parseArray(Json.toJsonString(hashMap.get("applyIdList")));
		for (Object obj : jSONArray) {
			JSONObject dataJSON = (JSONObject) obj;
			String applyId = dataJSON.getString("applyId");
			if(!dataJSON.containsKey("isOk")){
				TransferApplyRecord record = transferApplyService.selectById(applyId);
				if(record.getStatus()==1){
					dataJSON.put("isOk","wait");
				}else if(record.getStatus()==0){
					dataJSON.put("isOk","true");
				}else{
					dataJSON.put("isOk","false");
				}
			}
		}
		return jSONArray;
	}
}
